package com.gerenboke.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.SelectById;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gerenboke.constans.SystemConstants;
import com.gerenboke.domain.ResponseResult;
import com.gerenboke.domain.entity.Menu;
import com.gerenboke.domain.vo.MenuListForVo;
import com.gerenboke.domain.vo.MenuListVo;
import com.gerenboke.domain.vo.RoleSaveAndUpdateVo;
import com.gerenboke.enums.AppHttpCodeEnum;
import com.gerenboke.exception.SystemException;
import com.gerenboke.mapper.MenuMapper;
import com.gerenboke.service.MenuService;
import com.gerenboke.utils.BeanCopyUtils;
import com.gerenboke.utils.SecurityUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author makejava
 * @since 2022-11-16 23:30:11
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Override
    public List<String> selectPermsByUserId(Long id) {
        //如果是管理员，返回所有的权限
        if(SecurityUtils.isAdmin()){
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType, SystemConstants.MENU,SystemConstants.BUTTON);
            wrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
            List<Menu> menus = list(wrapper);
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则返回所具有的权限
        return getBaseMapper().selectPermsByUserId(id);
    }

    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Long userId) {
        MenuMapper menuMapper = getBaseMapper();
        List<Menu> menus = null;
        //判断是否是管理员
        if(SecurityUtils.isAdmin()){
            //如果是 获取所有符合要求的Menu
            menus = menuMapper.selectAllRouterMenu();
        }else{
            //否则  获取当前用户所具有的Menu
            menus = menuMapper.selectRouterMenuTreeByUserId(userId);
        }

        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<Menu> menuTree = builderMenuTree(menus,0L);
        return menuTree;
    }

    @Override
    public ResponseResult selectMenu(String status, String menuName) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Objects.nonNull(status),Menu::getStatus,status);
        queryWrapper.like(Objects.nonNull(menuName),Menu::getMenuName,menuName);
        queryWrapper.orderByAsc(Menu::getOrderNum);
        queryWrapper.orderByAsc(Menu::getId);
        List<Menu> list = list(queryWrapper);
        List<MenuListVo> menuListVos = BeanCopyUtils.copyBeanList(list, MenuListVo.class);
        return ResponseResult.okResult(menuListVos);
    }

    @Override
    public ResponseResult updateMenu(Menu menu) {
        Long parentId = menu.getParentId();
        Menu parenMenu = getById(parentId);
        if (parenMenu.getMenuName().equals(menu.getMenuName())){
            throw new SystemException(AppHttpCodeEnum.SYSTEM_MENU_ERROR);
        }
        else {
            updateById(menu);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult deleteMenu(Long menuId) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId,menuId);
        Long count = getBaseMapper().selectCount(queryWrapper);
        if (count>0){
            throw new SystemException(AppHttpCodeEnum.DELETE_MENU_ERROR);
        }else {
            getBaseMapper().deleteById(menuId);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult selectMenuListr() {
        List<Menu> menus = list();
//        List<Menu> menus = getBaseMapper().selectAllRouterMenu();
        List<MenuListForVo> menuListForVos = new ArrayList<>();
        for (Menu menu : menus) {
            MenuListForVo menuListForVo = new MenuListForVo();
            menuListForVo.setId(menu.getId());
            menuListForVo.setLabel(menu.getMenuName());
            menuListForVo.setParentId(menu.getParentId());
            menuListForVos.add(menuListForVo);
        }
        List<MenuListForVo> menuTree = builderMenuTrees(menuListForVos, 0L);
        return ResponseResult.okResult(menuTree);
    }

    @Override
    public ResponseResult roleMenuTreeselect(Long id) {
        List<Menu> menus = list();
//        List<Menu> menus = getBaseMapper().selectAllRouterMenu();
        List<MenuListForVo> menuListForVos = new ArrayList<>();
        for (Menu menu : menus) {
            MenuListForVo menuListForVo = new MenuListForVo();
            menuListForVo.setId(menu.getId());
            menuListForVo.setLabel(menu.getMenuName());
            menuListForVo.setParentId(menu.getParentId());
            menuListForVos.add(menuListForVo);
        }
        List<MenuListForVo> menuTree = builderMenuTrees(menuListForVos, 0L);
        List<String> MenuIds = getBaseMapper().selectRoleAndMenu(id);
        return ResponseResult.okResult(new RoleSaveAndUpdateVo(menuTree,MenuIds));
    }

    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }
    private List<MenuListForVo> builderMenuTrees(List<MenuListForVo> menus, Long parentId) {
        List<MenuListForVo> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     * @param menu
     * @param menus
     * @return
     */
    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m->m.setChildren(getChildren(m,menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
    private List<MenuListForVo> getChildren(MenuListForVo menu, List<MenuListForVo> menus) {
        List<MenuListForVo> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m->m.setChildren(getChildren(m,menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}

